package com.promote.hotspot.server.netty.pusher;

import com.google.common.collect.Queues;
import com.promote.hotspot.server.model.AppInfo;
import com.promote.hotspot.server.netty.holder.ClientInfoHolder;
import org.apache.commons.collections.CollectionUtils;
import org.promote.hotspot.common.model.HotKeyModel;
import org.promote.hotspot.common.model.HotSpotMsg;
import org.promote.hotspot.common.model.MessageType;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author enping.jep
 * @date 2024/01/17 16:03
 **/
@Component
public class ServerPusher implements IPusher {
    private static ExecutorService threadPoolExecutor = Executors.newSingleThreadExecutor();

    private static LinkedBlockingQueue<HotKeyModel> hotSpotQueue = new LinkedBlockingQueue<>();

    @Override
    public void push(HotKeyModel model) {
        hotSpotQueue.offer(model);
    }

    @PostConstruct
    public void batchPushToClient() {
        threadPoolExecutor.submit(() -> {
            while (true) {
                try {
                    List<HotKeyModel> tempModels = new ArrayList<>();
                    //要么key达到1千个，要么达到1秒，就汇总上报给etcd一次
                    // hotSpotQueue-阻塞队列  tempModels-将阻塞队列中的元素放入该集合中  numElements-取多少个放入 超时时间和单位
                    Queues.drain(hotSpotQueue, tempModels, 1000, 1, TimeUnit.SECONDS);
                    if (CollectionUtils.isEmpty(tempModels)) {
                        continue;
                    }

                    Map<String, List<HotKeyModel>> allAppHotKeyModels = new HashMap<>();

                    //拆分出每个app的热key集合，按app分堆
                    for (HotKeyModel hotKeyModel : tempModels) {
                        //如果map中没有(Absent)相应的key，则执行lambda表达式生成一个默认值并放入map中并返回，否则返回map中已有的值。
                        List<HotKeyModel> oneAppModels = allAppHotKeyModels.computeIfAbsent(hotKeyModel.getAppName(), key -> new ArrayList<>());
                        oneAppModels.add(hotKeyModel);
                    }

                    //遍历所有app，进行推送
                    for (AppInfo appInfo : ClientInfoHolder.apps) {
                        List<HotKeyModel> list = allAppHotKeyModels.get(appInfo.getAppName());
                        if (CollectionUtils.isEmpty(list)) {
                            continue;
                        }

                        HotSpotMsg hotSpotMsg = new HotSpotMsg(MessageType.RESPONSE_NEW_KEY);
                        hotSpotMsg.setHotKeyModels(list);

                        //整个app全部发送
                        appInfo.groupPush(hotSpotMsg);
                    }
                    allAppHotKeyModels = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
